from flask import Flask, jsonify, request
import cv2
import math
import time
import numpy as np

app = Flask(__name__)

qrPoint = [(262, 237), (314, 242), (308, 293), (258, 289)]  # 二维码标准位置
qrLine = (242, 314, 293, 308)  # 二维码标准判断线


# 运行状态常量
class DataManager:
    def __init__(self):
        # 初始化常量
        self.data = ""

    def update_constant(self, new_value):
        # 更新常量的值
        self.data = new_value

    def get_constant(self):
        # 获取常量的值
        return self.data


manager = DataManager()


# 计算偏转角度
def calculate_angle_between_lines(line1, line2):
    # 确保线段都是 (x1, y1, x2, y2) 格式的
    x1, y1, x2, y2 = line1
    x3, y3, x4, y4 = line2

    # 计算第一条线的方向向量
    vector1 = (x2 - x1, y2 - y1)

    # 计算第二条线的方向向量
    vector2 = (x4 - x3, y4 - y3)

    # 计算两个向量之间的点积
    dot_product = vector1[0] * vector2[0] + vector1[1] * vector2[1]

    # 计算向量的长度
    length1 = math.sqrt(vector1[0] ** 2 + vector1[1] ** 2)
    length2 = math.sqrt(vector2[0] ** 2 + vector2[1] ** 2)

    # 计算夹角的余弦值
    cosine_similarity = dot_product / (length1 * length2)

    # 计算夹角的弧度
    angle_in_radians = math.acos(cosine_similarity)

    # 将弧度转换为度
    angle_in_degrees = math.degrees(angle_in_radians)

    return angle_in_degrees


# 判读位置
def compare_points(points1, points2):
    if len(points2) != 4:
        # 确保points2包含四个点
        return False

    for i in range(4):
        x1, y1 = points1[i]
        x2, y2 = points2[i]

        if abs(x1 - x2) > 50 or abs(y1 - y2) > 50:
            # 如果任何一个点的XY偏移大于50，返回False
            return False

    # 所有点的XY偏移都不大于5，返回True
    return True


# 质检接口，判断是否质检合格返回
@app.route('/process_image', methods=['GET'])
def process_image():
    manager.__init__()
    angle_offset_str = "no "
    is_position_correct = False
    res = "没有检测到二维码"
    successful_detection_count = 0  # 用于追踪成功检测的次数

    try:
        for _ in range(3):
            manager.update_constant("正在读取图像")
            cap = cv2.VideoCapture(0)
            # 读取一帧图像
            ret, frame = cap.read()

            cap.release()

            if ret:  # 确保成功读取图像
                cv2.imwrite('frame.jpg', frame)

            detect_obj = cv2.wechat_qrcode_WeChatQRCode('detect.prototxt', 'detect.caffemodel', 'sr.prototxt',
                                                        'sr.caffemodel')

            img = cv2.imread('frame.jpg')
            manager.update_constant("正在确定二维码位置")
            res, points = detect_obj.detectAndDecode(img)

            if points:  # 如果检测到二维码
                array_data = points[0]
                line2 = (array_data[1, 1], array_data[1, 0], array_data[2, 1], array_data[2, 0])
                manager.update_constant("正在计算位置与角度")
                is_position_correct = compare_points(qrPoint, array_data)
                angle = calculate_angle_between_lines(qrLine, line2)
                angle_offset_str = str(angle)

                if angle < 10 and res and is_position_correct:
                    successful_detection_count += 1
                    break  # 检测到二维码后跳出循环

        # 如果在三次检测中至少有一次成功检测到二维码
        if successful_detection_count > 0:
            is_pass = True
        else:
            is_pass = False

        # 构建响应数据
        response_data = {
            'is_pass': is_pass,
            'is_position_correct': is_position_correct,
            'angle_offset': angle_offset_str + 'degrees',
            'info': res
        }

        manager.update_constant("返回结果中")

        return jsonify(response_data)

    except Exception as e:
        return jsonify({'error': str(e)})


# 质检接口，纯数据返回
@app.route('/process_image_data', methods=['GET'])
def process_image_data():
    manager.__init__()
    angle_offset_str = "no "
    successful_detection_count = 0  # 用于追踪成功检测的次数

    try:
        for _ in range(3):
            manager.update_constant("正在读取图像")
            cap = cv2.VideoCapture(0)
            # 读取一帧图像
            ret, frame = cap.read()

            cap.release()

            if ret:  # 确保成功读取图像
                cv2.imwrite('frame.jpg', frame)

            detect_obj = cv2.wechat_qrcode_WeChatQRCode('detect.prototxt', 'detect.caffemodel', 'sr.prototxt',
                                                        'sr.caffemodel')

            img = cv2.imread('frame.jpg')

            manager.update_constant("正在确定二维码位置")
            res, points = detect_obj.detectAndDecode(img)

            if not points:
                array_data_list = []
                res = "未检测到二维码"
            else:
                array_data = points[0]
                # 将NumPy数组转换为Python列表
                array_data_list = array_data.tolist()

                manager.update_constant("正在计算角度")
                line2 = (array_data[1, 1], array_data[1, 0], array_data[2, 1], array_data[2, 0])
                angle = calculate_angle_between_lines(qrLine, line2)
                angle_offset_str = str(angle)

            if points:  # 如果检测到二维码
                successful_detection_count += 1
                break  # 检测到二维码后跳出循环

        # 构建响应数据
        response_data = {
            'position_correct': array_data_list,
            'angle_offset': angle_offset_str,
            'info': res
        }

        manager.update_constant("返回结果中")
        return jsonify(response_data)

    except Exception as e:
        return jsonify({'error': str(e)})


# 获取质检运行状态
@app.route('/state', methods=['GET'])
def state():
    return manager.get_constant()


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
